package com.arcaneshift.servlet.util.parser;

import java.io.InputStream;
import java.util.List;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;

import com.arcaneshift.model.abstracts.AbstractArenaObject;
import com.arcaneshift.model.action.game.BattlePlayer;
import com.arcaneshift.model.action.game.Player;
import com.arcaneshift.model.request.GetStartGameStatsRequest;
import com.arcaneshift.model.response.GetStartGameStatsResponse;
import com.arcaneshift.model.util.TerranType;
import com.arcaneshift.servlet.abstracts.XMLParserBase;
import com.arcaneshift.servlet.util.network.HTTPProtocol;
import com.common.model.abstracts.AbstractRequest;
import com.common.model.abstracts.AbstractResponse;
import com.common.security.exceptions.HTTPException;
import com.common.security.exceptions.ParserException;

public class GetStartGameStatsXMLParser extends XMLParserBase {

	@Override
	public AbstractRequest parseRequest(InputStream stream) throws ParserException, HTTPException {
		GetStartGameStatsRequest request = new GetStartGameStatsRequest();
		
		Document document = createDocument(stream);
		
		Node actionNode = getActionNode(document);
		Node contentNode = getContentNode(document);
		
		insertAction(actionNode, request);
		Element element = getContent(contentNode);
		
		Element game = getElement(element, HTTPProtocol.GAME);
		request.setGameId(game.getAttribute(HTTPProtocol.ATTRIBUTE_VALUE));
		
		try {
			int player = Integer.parseInt(game.getAttribute(HTTPProtocol.ATTRIBUTE_PLAYER));
			request.setPlayer(player);
		} catch (NumberFormatException exception) {
			throw new ParserException(ParserException.CONVERSION_EXCEPTION);
		}
		
		return request;
	}

	@Override
	public String parseResponse(AbstractResponse abstractResponse) throws ParserException {
		GetStartGameStatsResponse response = null;
		if (abstractResponse instanceof GetStartGameStatsResponse) {
			response = (GetStartGameStatsResponse) abstractResponse;
		} else {
			throw new ParserException(ParserException.RESPONSE_MATCH_ERROR);
		}
		
		StringBuilder builder = new StringBuilder();
		List<List<TerranType>> terran = response.getTerran().getMatrix();
		List<List<AbstractArenaObject>> arena = response.getArena().get();
		List<BattlePlayer> battlePlayers = response.getBattlePlayers();
		
		if (terran.size() != arena.size()) {
			throw new ParserException(ParserException.RESPONSE_BAD_FORMAT);
		}
		
		builder.append(HTTPProtocol.RESPONSE_TAG);
		builder.append(HTTPProtocol.CLOSE_TAG);
		builder.append(HTTPProtocol.END_LINE);
		builder.append(getAction(response.getRequestAction()));
		builder.append(HTTPProtocol.CONTENT_TAG);
		builder.append(HTTPProtocol.END_LINE);
		
		for (BattlePlayer battlePlayer : battlePlayers) {
			builder.append(createPlayerTag(battlePlayer.getPlayerNumber(), 
					battlePlayer.getDeck().getCards().size()));
			builder.append(HTTPProtocol.END_LINE);
		}
		
		builder.append(HTTPProtocol.TERRAN_TAG);
		builder.append(HTTPProtocol.SPACE);
		builder.append(HTTPProtocol.VALUE_ATTRIBUTE);
		builder.append(response.getTerran().getName());
		builder.append(HTTPProtocol.END_ATTRIBUTE);
		builder.append(HTTPProtocol.CLOSE_TAG);
		builder.append(HTTPProtocol.END_LINE);
		builder.append(getGameMatrix(terran));
		builder.append(HTTPProtocol.TERRAN_END_TAG);
		builder.append(HTTPProtocol.END_LINE);
		builder.append(HTTPProtocol.ARENA_TAG);
		builder.append(HTTPProtocol.CLOSE_TAG);
		builder.append(HTTPProtocol.END_LINE);
		builder.append(getGameMatrix(arena));
		builder.append(HTTPProtocol.ARENA_END_TAG);
		builder.append(HTTPProtocol.END_LINE);
		builder.append(HTTPProtocol.CONTENT_END_TAG);
		builder.append(HTTPProtocol.END_LINE);
		builder.append(HTTPProtocol.RESPONSE_END_TAG);
		
		return builder.toString();
	}

	@Override
	protected <T> String eval(T item) {
		StringBuilder builder = new StringBuilder();
		
		if (item instanceof TerranType) {
			TerranType terranType = (TerranType) item;
			
			builder.append(terranType.name());
		} else if (item instanceof AbstractArenaObject) {
			AbstractArenaObject object = (AbstractArenaObject) item;
			
			builder.append(object.getName());
			builder.append(HTTPProtocol.END_ATTRIBUTE);
			builder.append(HTTPProtocol.TYPE_ATTRIBUTE);
			builder.append(object.getType());
			builder.append(HTTPProtocol.END_ATTRIBUTE);
			builder.append(HTTPProtocol.PLAYER_ATTRIBUTE);
			builder.append(object.getPlayerNumber());
		}
		
		return builder.toString();
	}
	
	private String createPlayerTag(int playerNumber, int deckSize) {
		StringBuilder builder = new StringBuilder();
		
		builder.append(HTTPProtocol.PLAYER_TAG);
		builder.append(HTTPProtocol.SPACE);
		builder.append(HTTPProtocol.VALUE_ATTRIBUTE);
		builder.append(playerNumber);
		builder.append(HTTPProtocol.END_ATTRIBUTE);
		builder.append(HTTPProtocol.SPACE);
		builder.append(HTTPProtocol.DECK_SIZE_ATTRIBUTE);
		builder.append(deckSize);
		builder.append(HTTPProtocol.END_ATTRIBUTE);
		builder.append(HTTPProtocol.END_TAG);
		
		return builder.toString();
	}
}
